package com.treasure.mall.biz.service.core.statistics.impl;

import com.treasure.mall.biz.base.AbstractSearchableCrudService;
import com.treasure.mall.biz.base.SpecificationAndSort;
import com.treasure.mall.biz.dto.BaseSaveDTO;
import com.treasure.mall.biz.dto.BaseSearchDTO;
import com.treasure.mall.biz.entity.statistics.DealAmountStatisticsPO;
import com.treasure.mall.biz.entity.statistics.DealAmountStatisticsPO_;
import com.treasure.mall.biz.repository.statistics.DealAmountStatisticsRepository;
import com.treasure.mall.biz.service.core.statistics.DealAmountStatisticsService;
import com.treasure.mall.zbq.common.Jsr310Utils;
import com.treasure.mall.zbq.common.SqlDataReader;
import com.treasure.mall.zbq.common.ienum.order.OrderEnums;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @author allan
 * @version 1.0.0
 * @date 2020/10/9
 */
@Service
public class DealAmountStatisticsServiceImpl extends AbstractSearchableCrudService<DealAmountStatisticsPO, Long> implements DealAmountStatisticsService {
    private DealAmountStatisticsRepository statisticsRepository;

    @Autowired
    protected DealAmountStatisticsServiceImpl(DealAmountStatisticsRepository repository) {
        super(repository);
        statisticsRepository = repository;
    }

    @Override
    protected SpecificationAndSort<DealAmountStatisticsPO> specificationAndSort(BaseSearchDTO searchDTO) {

        return null;
    }

    @Override
    public void statistics(LocalDate date) {
        if (statisticsRepository.existsByDate(date)) {
            return;
        }

        DealAmountStatisticsPO po = new DealAmountStatisticsPO();
        po.setDate(date);
        //昨日的
        LocalDateTime start = date.atStartOfDay();
        LocalDateTime end = Jsr310Utils.Date.endOfDay(date);

        String sqlWhere = " and create_time >= '" + Jsr310Utils.DateTime.asString(start) + "' and create_time <='" + Jsr310Utils.DateTime.asString(end) + "'";

        //已支付，各第三方支付，余额支付
        String sql = "select ifnull(sum(amount),0) as amount,pay_type from zb_payment_bill " +
                "where pay_status=1 and deal_type=0 " + sqlWhere +
                "group by pay_type";
        List<SqlDataReader> readers = executeReaderList(sql);
        BigDecimal payedAmount = BigDecimal.ZERO;
        BigDecimal alipayAmount = BigDecimal.ZERO;
        BigDecimal wechatAmount = BigDecimal.ZERO;
        BigDecimal balanceAmount = BigDecimal.ZERO;
        for (SqlDataReader sqlDataReader : readers) {
            int payType = sqlDataReader.getInteger("pay_type");
            BigDecimal amount = sqlDataReader.getBigDecimal("amount");
            if (payType == OrderEnums.PayType.ALI_PAY.getCode()) {
                alipayAmount = alipayAmount.add(amount);
            } else if (payType == OrderEnums.PayType.BALANCE_PAY.getCode()) {
                balanceAmount = balanceAmount.add(amount);
            } else {
                wechatAmount = wechatAmount.add(amount);
            }
            payedAmount = payedAmount.add(amount);
        }
        po.setPayedAmount(payedAmount);
        po.setBalanceAmount(balanceAmount);
        po.setAlipayAmount(alipayAmount);
        po.setWechatAmount(wechatAmount);
        //待支付
        sql = "SELECT ifnull(sum(final_amount),0) as finalAmount FROM zb_order where pay_status=0" + sqlWhere;
        SqlDataReader reader = executeReader(sql);
        po.setUnpayAmount(reader.getBigDecimal("finalAmount"));
        //退款的
        sql = "select ifnull(sum(amount),0) as amount,pay_type from zb_refund_bill " +
                "where is_success=1 and deal_type=0 " + sqlWhere +
                "group by pay_type";
        readers = executeReaderList(sql);
        BigDecimal refundAmount = BigDecimal.ZERO;
        BigDecimal alipayRefund = BigDecimal.ZERO;
        BigDecimal wechatRefund = BigDecimal.ZERO;
        BigDecimal balanceRefund = BigDecimal.ZERO;
        for (SqlDataReader sqlDataReader : readers) {
            BigDecimal amount = sqlDataReader.getBigDecimal("amount");
            int payType = sqlDataReader.getInteger("pay_type");
            if (payType == OrderEnums.PayType.ALI_PAY.getCode()) {
                alipayRefund = alipayRefund.add(amount);
            } else if (payType == OrderEnums.PayType.BALANCE_PAY.getCode()) {
                balanceRefund = balanceRefund.add(amount);
            } else {
                wechatRefund = wechatRefund.add(amount);
            }
            refundAmount = refundAmount.add(amount);
        }
        po.setRefundAmount(refundAmount);
        po.setAlipayRefund(alipayRefund);
        po.setWechatRefund(wechatRefund);
        po.setBalanceRefund(balanceRefund);

        save(po);
    }

    @Override
    public List<DealAmountStatisticsPO> sevenDays() {
        LocalDate end = LocalDate.now().minusDays(1);
        LocalDate begin = end.minusDays(7);

        return statisticsRepository.findByDateIsBetween(begin, end);
    }

    @Override
    public Page<DealAmountStatisticsPO> findAll(int pageIndex, int pageSize, String begin, String end) {
        Specification<DealAmountStatisticsPO> specification = ((root, cq, cb) -> {
            List<Predicate> predicates = new ArrayList<>();

            if (StringUtils.isNotEmpty(begin)) {
                LocalDate beginDate = Jsr310Utils.DateTime.of(begin).toLocalDate();
                predicates.add(cb.greaterThanOrEqualTo(root.get(DealAmountStatisticsPO_.date), beginDate));
            }
            if (StringUtils.isNotEmpty(end)) {
                LocalDate endDate = Jsr310Utils.DateTime.of(end).toLocalDate();
                predicates.add(cb.lessThanOrEqualTo(root.get(DealAmountStatisticsPO_.date), endDate));
            }

            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        });

        return statisticsRepository.findAll(specification, PageRequest.of(pageIndex - 1, pageSize, Sort.Direction.DESC, "date"));
    }

    @Override
    public Page<DealAmountStatisticsPO> findAll(int pageIndex, int pageSize) {
        return statisticsRepository.findAll(PageRequest.of(pageIndex - 1, pageSize, Sort.Direction.DESC, "date"));
    }

    @Override
    public DealAmountStatisticsPO save(BaseSaveDTO saveDTO) {
        return null;
    }
}
